package com.proposition.web.user;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.proposition.commons.model.Permission;
import com.proposition.commons.model.Role;
import com.proposition.commons.model.RolePermission;
import com.proposition.commons.utils.Node;
import com.proposition.commons.utils.State;
import com.proposition.support.annotation.LogAnnotation;
import com.proposition.support.utils.Rest;
import com.proposition.user.service.PermissionService;
import com.proposition.user.service.RolePermissionService;
import com.proposition.user.service.RoleService;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * ${DESCRIPTION}
 *
 * @author 杨凯
 * @create 2017-11-01 9:36
 **/
@Controller
@RequestMapping("/role")
public class RoleController {
	private static final Logger logger = LoggerFactory.getLogger(RoleController.class);

	private RoleService roleService;

	private PermissionService permissionService;

	private RolePermissionService rolePermissionService;

	@Autowired
	public RoleController(RoleService roleService, PermissionService permissionService, RolePermissionService rolePermissionService) {
		this.roleService = roleService;
		this.permissionService = permissionService;
		this.rolePermissionService = rolePermissionService;
	}
	@RequiresRoles("admin")
	@RequestMapping("/roleListPage")
	public String roleListPage(Model model) {
		model.addAttribute("roleList", roleService.findRoleList());
		return "user/role-list";
	}

	@RequiresRoles("admin")
	@RequestMapping("/roleAddPage")
	public String addRolePage() {
		return "user/role-add";
	}


	@RequestMapping("/menu")
	@ResponseBody
	public List<Node> getMenu() throws Exception {
		Node tree = getTreeJson();//获得一棵树模型的数据
		return tree.getNodes();
	}

	public Node getTreeJson() {
		List<Permission> reslist = permissionService.selectList(new EntityWrapper<>());//从数据库获取所有资源
		List<Node> nodes = new ArrayList<Node>();//把所有资源转换成树模型的节点集合，此容器用于保存所有节点
		for (Permission res : reslist) {

			Node node = new Node();
			node.setId(res.getId());
			node.setNodeId(res.getNodeId());
			node.setPid(res.getPid());
			node.setText(res.getName());
			nodes.add(node);//添加到节点容器

		}
		Node tree = new Node();//重要插件，创建一个树模型
		Node mt = tree.createTree(nodes);//Node类里面包含了一个创建树的方法。这个方法就是通过节点的信息（nodes）来构建一颗多叉树manytree->mt。
		return mt;
	}

	@RequiresRoles("admin")
	@LogAnnotation(moduleName = "角色模块", operate = "角色添加")
	@ResponseBody
	@PostMapping("/addRole")
	public Rest addRole(@RequestParam("title") String title, @RequestParam("permissionId") Integer[] permissionId) {
		Rest.Builder rest = Rest.newBuilder();
		try {
			roleService.addRole(title, permissionId);
		} catch (Exception e) {
			logger.error("角色添加失败[{}]", e.getMessage());
			return rest.status(1001).build();
		}
		return rest.status(1000).build();
	}

	@RequiresRoles("admin")
	@ResponseBody
	@PostMapping("/checkRoleExist")
	public Rest checkRoleTitle(@RequestParam String title) {
		Rest.Builder rest = Rest.newBuilder();
		//查询角色名称是否存在
		Integer count = roleService.selectCount(new EntityWrapper<Role>().where("r_title={0}", title));
		if (count != 0) {
			//角色名称已存在
			return rest.status(1001).build();
		}
		return rest.status(1000).build();
	}


	/**
	 * 删除角色
	 *
	 * @return
	 */
	@RequiresRoles("admin")
	@LogAnnotation(moduleName = "角色模块", operate = "角色删除")
	@ResponseBody
	@PostMapping("/delete/{roleId}")
	public Rest deleteRole(@PathVariable("roleId") Integer roleId) {
		Rest.Builder rest = Rest.newBuilder();
		try {
			boolean result = roleService.deleteRole(roleId);
			if (!result) {
				//当前角色下存在用户 不能删除
				return rest.status(1001).build();
			}
		} catch (Exception e) {
			logger.error("角色删除异常[{}]", e.getMessage());
			return rest.status(1002).build();
		}
		//删除成功
		return rest.status(1000).build();
	}

	/**
	 * 角色修改页面
	 *
	 * @return
	 */
	@RequiresRoles("admin")
	@GetMapping("/update")
	public String update(Model model, @RequestParam("roleId") Integer roleId) {
		model.addAttribute("role", roleService.selectById(roleId));
		model.addAttribute("roleId", roleId);
		return "user/role-edit";
	}

	/**
	 * 角色详情
	 *
	 * @param roleId
	 * @return
	 */
	@RequiresRoles("admin")
	@GetMapping("/update/{roleId}")
	@ResponseBody
	public List<Node> roleUpdate(@PathVariable("roleId") Integer roleId) throws JsonProcessingException {
		Wrapper<RolePermission> wrapper = new EntityWrapper<>();
		wrapper.where("r_role_id={0}", roleId);
		List<RolePermission> rolePermissions = rolePermissionService.selectList(wrapper);
		List<Permission> reslist = permissionService.selectList(new EntityWrapper<>());//从数据库获取所有资源
		List<Node> nodes = new ArrayList<Node>();//把所有资源转换成树模型的节点集合，此容器用于保存所有节点
		for (Permission res : reslist) {

			Node node = new Node();
			node.setId(res.getId());
			node.setNodeId(res.getNodeId());
			node.setPid(res.getPid());
			node.setText(res.getName());
			for(RolePermission permission : rolePermissions){
				if(permission.getPermissionId() == res.getId()){
					State state = new State();
					state.setChecked(true);
					node.setState(state);
				}
			}
			nodes.add(node);//添加到节点容器

		}
		Node tree = new Node();//重要插件，创建一个树模型
		Node mt = tree.createTree(nodes);//Node类里面包含了一个创建树的方法。这个方法就是通过节点的信息（nodes）来构建一颗多叉树manytree->mt。
		return mt.getNodes();
	}
	@RequiresRoles("admin")
	@LogAnnotation(moduleName = "角色模块", operate = "角色修改")
	@PutMapping("/update")
	@ResponseBody
	public Rest roleUpdate(@RequestParam("roleId") Integer roleId, @RequestParam("permissionId") Integer[] permissionId) {
		Rest.Builder rest = Rest.newBuilder();
		try {
			roleService.updateRole(roleId, permissionId);
		} catch (Exception e) {
			logger.error("角色修改失败[{}]", e.getMessage());
			return rest.status(1001).build();
		}

		return rest.status(1000).build();
	}
}
